﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web;
using System.Web.Routing;

namespace ProjectBase.Core.Utils
{
    /// <summary>
    ///     Utils for special purposes
    /// </summary>
    public static partial class Ext
    {
        #region CleanDirtyString
        /// <summary>
        ///     string is firstly cleaned from accents (ReplaceDiacritics())
        ///     and then only sings ( A-Z a-z 0-9 ) are left
        /// </summary>
        /// <param name = "value"></param>
        /// <param name = "doReplaceDiacritics">default is true. If set to false, diacritics is not replaced
        ///     (and such chars are lost)</param>
        /// <returns></returns>
        public static string CleanDirtyString(this string value, bool doReplaceDiacritics = true)
        {
            var dirtyString = doReplaceDiacritics ? value.ReplaceDiacritics() : value;
            var cleanString = Regex.Replace(dirtyString, "[^A-Za-z0-9]", "");
            return cleanString;
        }

        /// <summary>
        ///     replace the accents etc. (e.g. řšč to rsc).
        /// </summary>
        /// <see cref = "http://weblogs.asp.net/fmarguerie/archive/2006/10/30/removing-diacritics-accents-from-strings.aspx" />
        /// <param name = "value"></param>
        /// <returns></returns>
        public static string ReplaceDiacritics(this string value)
        {
            var normalizedString = value.Normalize(NormalizationForm.FormD);
            var sb = new StringBuilder();

            foreach (var c in normalizedString)
            {
                if (CharUnicodeInfo.GetUnicodeCategory(c)
                    != UnicodeCategory.NonSpacingMark)
                {
                    sb.Append(c);
                }
            }

            return sb.ToString();
        }
        #endregion CleanDirtyString

        #region Utils
        /// <summary>
        ///     if connection string contains DataSource="|DataDirectory|",
        ///     corrected absolute path is inserted instead
        /// </summary>
        /// <param name="inputString"></param>
        /// <returns></returns>
        public static string ReplaceDataSource(this string inputString)
        {
            if (!inputString.Contains("Data Source")
             && !inputString.Contains("|DataDirectory|"))
            {
                return inputString;
            }
            var result = new StringBuilder();
            var split = inputString.Split(';');
            foreach (var part in split)
            {
                var pair = part.Split('=');
                if (pair[0].Trim().Equals("Data Source") && pair.Length > 1)
                {
                    result.Append("Data Source=" + pair[1].ReplaceDataDirectory() + ";");
                }
                else
                {
                    result.Append(part + ";");
                }
            }
            return result.ToString();
        }

        /// <summary>
        ///     if connection string's DataSource value starts with "|DataDirectory|",
        ///     corrected absolute path is inserted instead
        /// </summary>
        /// <param name="inputString"></param>
        /// <returns></returns>
        public static string ReplaceDataDirectory(this string inputString)
        {
            var str = inputString.Trim();
            if (inputString.IsEmpty()
                || !inputString.StartsWith("|DataDirectory|", StringComparison.InvariantCultureIgnoreCase))
            {
                return str;
            }

            var length = "|DataDirectory|".Length;
            if ((inputString.Length > "|DataDirectory|".Length)
                && ('\\' == inputString["|DataDirectory|".Length]))
            {
                length++;
            }
            var file = inputString.Substring(length);

            var data = AppDomain.CurrentDomain.GetData("DataDirectory") as string;
            if (data.IsEmpty())
            {
                return Global.CreateAppDataPath(file);
            }
            return System.IO.Path.Combine(data, file);
        }
        #endregion Utils

        #region Language
        public static bool IsLanguageNameValid(this string languageName)
        {
            return languageName.IsNotEmpty()
                && CultureInfo.GetCultures(CultureTypes.AllCultures)
                .ToList()
                .Any(c => c.Name.Equals(languageName, StringComparison.Ordinal));
        }
        public static void SetCurrentCulture(this CultureInfo culture, string lang)
        {
            if (!lang.IsLanguageNameValid()
              || culture.Name.Equals(lang))
            {
                return;
            }
            Thread.CurrentThread.CurrentUICulture = new CultureInfo(lang);
            Thread.CurrentThread.CurrentCulture = new CultureInfo(CultureInfo.CurrentUICulture.TextInfo.CultureName);
        }
        #endregion Language

        #region RouteValues
        /// <summary>
        /// Converts the url (e.g. "http://server/controller/action"
        /// into the RouteData dictionary
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static RouteData GetRouteData(this string path)
        {
            var uri = new Uri(path);
            var request = new HttpRequest(null, uri.AbsoluteUri, uri.Query);
            using (var writer = new System.IO.StringWriter())
            {
                var response = new HttpResponse(writer);
                var httpContext = new HttpContext(request, response);

                return RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));
            }
        }
        #endregion RouteValues

        #region TryFindProperty
        public static bool TryFindProperty<T, TResult>(this T item, string propertyName, out TResult result)
            where T : class
            where TResult : class
        {
            var split = propertyName.Split('.');
            if (split.Length > 1)
            {
                object subItem;
                if (GetPropertyValue(item, split[0], out subItem))
                {
                    return TryFindProperty(subItem, propertyName.Substring(split[0].Length + 1), out result);
                }
                result = null;
                return false;
            }
            return GetPropertyValue(item, propertyName, out result);
        }
        public static bool GetPropertyValue<T, TResult>(this T item, string propertyName, out TResult result)
            where T : class
        {
            result = default(TResult);
            if (item.IsNull())
            {
                return false;
            }

            var type = item.GetType();

            var param = Expression.Parameter(typeof(object)); // param for FUNC
            var parameterName = Expression.Parameter(typeof(string));
            var parameterEntity = Expression.Convert(param, type); // converted param for Property expression

            try
            {
                var getPropertyValue = Expression.Property(parameterEntity, type, propertyName);
                var lambda = Expression.Lambda<Func<object, string, TResult>>(
                    Expression.Convert(getPropertyValue, typeof(TResult)), param, parameterName);
                result = lambda.Compile().Invoke(item, propertyName);
            }
            catch (Exception)
            {
                return false;
            }
            return result.Is();
        }
        #endregion TryFindProperty
    }
}